home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 30
/
Aminet 30 (1999)(Schatztruhe)[!][Apr 1999].iso
/
Aminet
/
util
/
pack
/
xpk_Source.lha
/
xpk_Source
/
xpkmaster
/
seek.c
< prev
next >
Wrap
C/C++ Source or Header
|
1998-11-09
|
5KB
|
173 lines
#ifndef XPKMASTER_SEEK_C
#define XPKMASTER_SEEK_C
/* Routinesheader
Name: seek.c
Main: xpkmaster
Versionstring: $VER: seek.c 1.0 (30.10.1998)
Author: SDI
Distribution: Freeware
Description: Implementation of XpkSeek
1.0 30.10.98 : first version
*/
#include <exec/memory.h>
#include <proto/exec.h>
#include <proto/xpkmaster.h>
#include "xpkmaster.h"
/* get chunk header and and seek data when necessary */
XPK_ALLINONE LONG addseek(struct XpkBuffer *xbuf)
{
LONG ulen;
struct SeekDataList *sdl;
if(!(xbuf->xb_Flags & XMF_SEEK))
return 0;
ulen = xbuf->xb_UCur;
/* check if already included */
sdl = xbuf->xb_SeekDataList;
while(sdl && sdl->sdl_Next)
sdl = sdl->sdl_Next;
if(sdl && sdl->sdl_Data[sdl->sdl_Used-1].sd_ULen >= ulen)
return 0; /* already done, so we quit */
if(!sdl || sdl->sdl_Used == SEEKENTRYNUM)
{
struct SeekDataList *sdl2;
if(!(sdl2 = (struct SeekDataList *)
AllocMem(sizeof(struct SeekDataList), MEMF_CLEAR|MEMF_PUBLIC)))
return (xbuf->xb_Result = XPKERR_NOMEM);
if(!xbuf->xb_SeekDataList)
xbuf->xb_SeekDataList = sdl2;
else
sdl->sdl_Next = sdl2;
sdl = sdl2;
}
sdl->sdl_Data[sdl->sdl_Used].sd_FilePos = xbuf->xb_InBufferPos;
sdl->sdl_Data[sdl->sdl_Used].sd_ULen = ulen;
sdl->sdl_Data[(sdl->sdl_Used)++].sd_CLen = xbuf->xb_CCur;
#ifdef DEBUG
DebugRunTime("addseek: added entry (pos %ld, ulen %ld)",
xbuf->xb_InBufferPos, ulen);
#endif
return 0;
}
XPK_ALLINONE void freeseek(struct XpkBuffer *xbuf)
{
struct SeekDataList *sdl, *sdl2;
sdl = xbuf->xb_SeekDataList;
while(sdl)
{
sdl2 = sdl->sdl_Next;
FreeMem(sdl, sizeof(struct SeekDataList));
sdl = sdl2;
}
xbuf->xb_SeekDataList = 0;
}
LONG doseek(struct XpkBuffer *xbuf, LONG pos)
{
LONG ulen, clen;
XpkChunkHeader *lochdr = &(xbuf->xb_Headers.h_Loc);
struct SeekDataList *sdl;
if(pos > xbuf->xb_Fib.xf_ULen)
return XPKERR_BADPARAMS;
if(xbuf->xb_Format == XPKMODE_UPUP)
{
xbuf->xb_Flags &= ~XMF_EOF;
if(!(hookread(xbuf, XIO_SEEK, 0, pos - xbuf->xb_InBufferPos)))
return xbuf->xb_Result;
xbuf->xb_Fib.xf_CCur = xbuf->xb_Fib.xf_UCur = xbuf->xb_InBufferPos;
xbuf->xb_Fib.xf_NLen = Min(xbuf->xb_InLen - xbuf->xb_Fib.xf_UCur,
DEFAULTCHUNKSIZE) + XPK_MARGIN;
return 0;
}
for(sdl = xbuf->xb_SeekDataList; sdl; sdl = sdl->sdl_Next)
{
LONG i;
for(i = 0; i < sdl->sdl_Used; ++i)
{
if(sdl->sdl_Data[i].sd_ULen > pos)
{
if(!(hookread(xbuf, XIO_SEEK, 0, sdl->sdl_Data[i].sd_FilePos -
xbuf->xb_Headers.h_LocSize - xbuf->xb_InBufferPos)))
return xbuf->xb_Result;
if(!(hookread(xbuf, XIO_READ, lochdr, xbuf->xb_Headers.h_LocSize)))
return xbuf->xb_Result;
getUClen(xbuf, &ulen, &clen);
xbuf->xb_UCur = sdl->sdl_Data[i].sd_ULen - ulen;
xbuf->xb_CCur = sdl->sdl_Data[i].sd_CLen - clen;
updatefib(xbuf);
return (LONG) (pos - xbuf->xb_Fib.xf_UCur);
}
}
}
/* this is called when need a forward seek and we do not have the seek
entries */
while(xbuf->xb_UCur <= pos)
{
if(lochdr->xch_Word.xchw_Type == XPKCHUNK_END)
return XPKERR_BADPARAMS;
getUClen(xbuf, &ulen, &clen);
if(!(hookread(xbuf, XIO_SEEK, 0, ROUNDLONG(clen))))
return xbuf->xb_Result;
if(!(hookread(xbuf, XIO_READ, lochdr, xbuf->xb_Headers.h_LocSize)))
return xbuf->xb_Result;
if(updatefib(xbuf))
return xbuf->xb_Result;
}
return (LONG) (pos - xbuf->xb_Fib.xf_UCur);
}
/**************************************************************************
*
* XpkSeek() - move around on a compressed file
*
*/
/* Return codes < 0 are error codes. Codes >= 0 are file position */
ASM(LONG) LIBXpkSeek(REG(a0, struct XpkBuffer *xbuf), REG(d0, LONG dist),
REG(d1, LONG mode))
{
LONG err = XPKERR_BADPARAMS;
if((xbuf->xb_Format != XPKMODE_UPSTD && xbuf->xb_Format != XPKMODE_UPUP) ||
(xbuf->xb_SubInfo->xi_Flags & (XPKIF_NOSEEK|XPKIF_PREREADHDR)))
err = XPKERR_NOFUNC;
else if(xbuf->xb_Flags & XMF_SEEK)
{
switch(mode)
{
case XPKSEEK_CURRENT: err = doseek(xbuf, xbuf->xb_Fib.xf_UCur + dist); break;
case XPKSEEK_BEGINNING: err = doseek(xbuf, dist); break;
case XPKSEEK_END: err = doseek(xbuf, xbuf->xb_Fib.xf_ULen + dist); break;
/* default: err = XPKERR_BADPARAMS; break; */
}
#ifdef DEBUG
DebugRunTime("XpkSeek: position after seek (pos %ld, ulen %ld)",
xbuf->xb_InBufferPos, xbuf->xb_Fib.xf_UCur);
#endif
}
return err;
}
#endif /* XPKMASTER_SEEK_C */